﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CrusadeGmTool.Net.IO;
using System.IO;
using System.Windows;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;

namespace CrusadeGmTool.Net
{
    public abstract class Packet
    {
        private const int BUFFER_SIZE = 4096;
        protected PacketWriter Stream;
        int _id;
        int? _length;
        string _name;

        #region Properties
        /// <summary>
        /// Gets the name of the packet
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        /// <summary>
        /// Gets the size in bytes of the packet
        /// </summary>
        public int? Length
        {
            get { return _length; }
        }

        /// <summary>
        /// Gets the Id, or Command that identifies the packet.
        /// </summary>
        public int Id
        {
            get { return _id; }
        }
        #endregion


        /// <summary>
        /// Creates an instance of a packet
        /// </summary>
        /// <param name="id">the Id, or Command that identifies the packet</param>
        /// <param name="name">The name of the packet</param>
        public Packet(int id, string name)
        {
            _id = id;
            _name = name;

            Stream = PacketWriter.CreateInstance(_length ?? 0);
            Stream.Write(id);
            Stream.Write((short)0);
        }

        public Packet()
        {
            Stream = PacketWriter.CreateInstance(0);
        }

        /// <summary>
        /// Creates an instance of a packet
        /// </summary>
        /// <param name="id">the Id, or Command that identifies the packet</param>
        /// <param name="name">The name of the packet</param>
        /// <param name="length">The size in bytes of the packet</param>
        public Packet(int id, string name, int? length)
        {
            _id = id;
            _name = name;
            _length = length;
            Stream = PacketWriter.CreateInstance(length ?? 0);
            Stream.Write((byte)id);
            Stream.Write((short)(length));
        }

        /// <summary>
        /// Resets the Packet Writer and ensures the packet's 2nd and 3rd bytes are used to store the length
        /// </summary>
        /// <param name="length"></param>
        public void EnsureCapacity(int? length)
        {
            Stream = PacketWriter.CreateInstance(length ?? 0);
            Stream.Write((byte)_id);
            Stream.Write((short)(length));
        }

        /// <summary>
        /// Create an array of byte ready to be sent
        /// </summary>
        /// <returns>the array of byte</returns>
        public byte[] Compile()
        {
            Stream.Flush();

            if (Length == 0)
            {
                long length = Stream.Length;
                Stream.Seek((long)1, SeekOrigin.Begin);
                Stream.Write((ushort)length);
                Stream.Flush();
            }
            return Stream.Compile();
        }

        public override string ToString()
        {
            return string.Format("Id: {0:X2} Name: {1} Length: {2}", _id, _name, _length ?? Stream.Length);
        }
    }
}
